package com.link.base.base.message.push.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.link.base.base.message.push.model.PushInfo;
import com.link.core.util.RedisUtil;
import com.link.core.util.redisclient.LinkRedisClient;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.List;

/**
 * 华为推送
 *
 * @author liyongfeng
 * @date 2019/05/13
 */
@Component
public class HuaweiPushServiceImpl {

    /**
     * 推送消息
     * 
     * @author ouyangzhenqiang
     * @date 2019/08/12 16:22
     * @param record 推送记录
     */
    void hwPush(PushInfo record) throws Exception {
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            String redisKey = "hwPushAccessToken_" + record.getAppId();
            boolean existed = jedis.exists(redisKey);
            String accessToken;
            if (!existed) {
                accessToken = refreshToken(record.getAppId());
            } else {
                accessToken = jedis.hget(redisKey, "accessToken");
                String tokenExpiredTime = jedis.hget(redisKey, "tokenExpiredTime");
                if (Long.valueOf(tokenExpiredTime) <= System.currentTimeMillis()) {
                    accessToken = refreshToken(record.getAppId());
                }
            }
            redisKey = "APP_PUSH_CONFIG";
            String appId = jedis.hget(redisKey, "hwPushAppID_" + record.getAppId());
            String apiUrl = jedis.hget(redisKey, "hwPushApiUrl");
            // 目标设备Token
            JSONArray deviceTokens = new JSONArray();
            deviceTokens.add(record.getPushServiceToken());
            // 仅通知栏消息需要设置标题和内容，透传消息key和value为用户自定义
            JSONObject body = new JSONObject();
            // 消息标题
            body.put("title", record.getPushTitle());
            // 消息内容体
            body.put("content", record.getPushNote());
            JSONObject param = new JSONObject();
            // 定义需要打开的应用包名
            param.put("appPkgName", record.getAppId());
            JSONObject action = new JSONObject();
            // 类型3为打开APP，其他行为请参考接口文档设置
            action.put("type", 3);
            // 消息点击动作参数
            action.put("param", param);
            JSONObject msg = new JSONObject();
            // 3: 通知栏消息，异步透传消息请根据接口文档设置
            msg.put("type", 3);
            // 消息点击动作
            msg.put("action", action);
            // 通知栏消息body内容
            msg.put("body", body);
            // 华为PUSH消息总结构体
            JSONObject hps = new JSONObject();
            hps.put("msg", msg);
            JSONObject payload = new JSONObject();
            payload.put("hps", hps);
            String postBody = MessageFormat.format(
                "access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
                URLEncoder.encode(accessToken, "UTF-8"),
                URLEncoder.encode("openpush.message.api.send", "UTF-8"),
                URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
                URLEncoder.encode(deviceTokens.toString(), "UTF-8"),
                URLEncoder.encode(payload.toString(), "UTF-8"));
            String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
            httpPost(postUrl, postBody, 5000, 5000);

        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    /**
     * 获取下发通知消息的认证Token
     *
     * @author liyongfeng
     * @date 2019/05/13
     * @param busAppId 应用Id
     */
    private String refreshToken(String busAppId) throws Exception {
        String accessToken;
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            String redisKey = "APP_PUSH_CONFIG";
            String appSecret = jedis.hget(redisKey, "hwPushAppSecret_" + busAppId);
            String tokenUrl = jedis.hget(redisKey, "hwPushTokenUrl");
            String appId = jedis.hget(redisKey, "hwPushAppID_" + busAppId);

            String msgBody = MessageFormat.format(
                "grant_type=client_credentials&client_secret={0}&client_id={1}",
                URLEncoder.encode(appSecret, "UTF-8"), appId);
            String response = httpPost(tokenUrl, msgBody, 5000, 5000);
            JSONObject obj = JSONObject.parseObject(response);
            accessToken = obj.getString("access_token");
            Long tokenExpiredTime = System.currentTimeMillis() + obj.getLong("expires_in") - 5 * 60 * 1000;

            redisKey = "hwPushAccessToken_" + busAppId;
            boolean existed = jedis.exists(redisKey);
            if (!existed) {
                jedis.hset(redisKey, "accessToken", accessToken);
                jedis.hset(redisKey, "tokenExpiredTime", tokenExpiredTime.toString());
                // 设置过期时间30天
                jedis.expire(redisKey, 30 * 86400);
            } else {
                jedis.hset(redisKey, "accessToken", accessToken);
                jedis.hset(redisKey, "tokenExpiredTime", tokenExpiredTime.toString());
            }
            return accessToken;
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }
    
    /**
     * 发送
     * 
     * @author ouyangzhenqiang
     * @date 2019/08/12 16:21
     * @param httpUrl
     * @param data
     * @param connectTimeout
     * @param readTimeout
     */
    private String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException {
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;

        try {
            URL url = new URL(httpUrl);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            urlConnection.setConnectTimeout(connectTimeout);
            urlConnection.setReadTimeout(readTimeout);
            urlConnection.connect();

            // POST data
            outPut = urlConnection.getOutputStream();
            outPut.write(data.getBytes("UTF-8"));
            outPut.flush();

            // read response
            if (urlConnection.getResponseCode() < 400) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
            }

            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines) {
                strBuf.append(line);
            }
            return strBuf.toString();
        } finally {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }


}
